package com.zhj.test.netty.codec;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;

/**
 * @author zhj
 */
public class NettyServer {
    public static void main(String[] args) throws InterruptedException {
        // 创建两个线程组 BossGroup 和 WorkerGroup
        // BossGroup 只处理连接请求 WorkerGroup 处理与客户端的业务处理
        // 两个线程组都是无限循环
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup(32);
        // 创建服务器端启动对象，配置参数
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            // 链式编程
            serverBootstrap.group(bossGroup,workerGroup) // 设置线程组
                    .channel(NioServerSocketChannel.class) // 设置NIO通道实现
                    .option(ChannelOption.SO_BACKLOG, 128) // 设置线程队列连接个数
                    .childOption(ChannelOption.SO_KEEPALIVE,true) // 设置保持活动连接状态
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        // 创建通道初始化对象
                        // 给pipeline 设置处理器
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            System.out.println("客户Channel" + socketChannel);
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            pipeline.addLast(new ProtobufDecoder(StudentPOJO.Student.getDefaultInstance()));
                            pipeline.addLast(new NettyServerHandler());
                        }
                    }); // 给workerGroup管道设置处理器
            System.out.println("服务器初始化完毕！！！");
            // 启动服务器，并绑定端口，并且同步处理
            ChannelFuture channelFuture = serverBootstrap.bind(6668).sync();

            channelFuture.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture channelFuture) throws Exception {
                    if (channelFuture.isSuccess()) {
                        System.out.println("端口绑定成功！");
                    } else {
                        System.out.println("端口绑定失败！");
                    }
                }
            });

            // 对关闭通道进行监听 （异步模型）
            channelFuture.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
